package core

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"math/rand"
	"time"
)

// B（字节）
// KB（千字节，1KB = 1024B）
// MB（兆字节，1MB = 1024KB）
// GB（吉字节，1GB = 1024MB）
// TB（太字节，1TB = 1024GB）
// PB（拍字节，1PB = 1024TB）
// EB（艾字节，1EB = 1024PB）
// ZB（泽字节，1ZB = 1024EB）
// YB（尧字节，1YB = 1024ZB）
// 转换字节数为人类可读格式
func GetFormatValue(bytes uint64) string {
	const (
		_  = iota
		KB = 1 << (10 * iota) // 1024
		MB
		GB
		TB
		PB
		EB
	)
	switch {
	case bytes >= EB:
		return fmt.Sprintf("%.2f PB", float64(bytes)/EB)
	case bytes >= PB:
		return fmt.Sprintf("%.2f PB", float64(bytes)/PB)
	case bytes >= TB:
		return fmt.Sprintf("%.2f TB", float64(bytes)/TB)
	case bytes >= GB:
		return fmt.Sprintf("%.2f GB", float64(bytes)/GB)
	case bytes >= MB:
		return fmt.Sprintf("%.2f MB", float64(bytes)/MB)
	case bytes >= KB:
		return fmt.Sprintf("%.2f KB", float64(bytes)/KB)
	default:
		return fmt.Sprintf("%d B", bytes)
	}
}
func GetNanoID() uint64 {
	return uint64(time.Now().UnixNano()) //time.Now().UnixMilli()
}

// 生成随机数
func GetRand(min, max int) int {
	if min >= max {
		return min
	}
	// 生成 [0, max-min] 的随机数，再加上 min 偏移
	return min + rand.Intn(max-min+1)
}

// 生成指定长度的随机字符串,包含大小写字母和数字
func GenerateRandomString(length uint64) (string, error) {
	// 定义字符集，可以根据需要修改
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

	if length <= 0 {
		return "", fmt.Errorf("length must >0")
	}

	result := make([]byte, length)

	for i := range result {
		// 生成0到charsetLength-1之间的随机数
		randomIndex := rand.Intn(len(charset) - 1)
		result[i] = charset[randomIndex]
	}

	return string(result), nil
}

func EncoderAnyDataToBytes(obj any) ([]byte, error) {
	var bufs bytes.Buffer
	encoder := gob.NewEncoder(&bufs)
	if err := encoder.Encode(obj); err != nil {
		return nil, err
	}
	return bufs.Bytes(), nil
}

// 参数obj需要初始化可容纳空间，如果是数组，则是需要明确大小，或再申明一个新结构体用保存该数组
func DecoderBytesToAnyData(data []byte, obj any) error {
	var bufs bytes.Buffer = *bytes.NewBuffer(data)
	decoder := gob.NewDecoder(&bufs)
	if err := decoder.Decode(obj); err != nil {
		return err
	}
	return nil
}
